package cn.caishen.report.service.system.impl;

import cn.caishen.report.common.config.LoginInformation;
import cn.caishen.report.common.constant.LbConstant;
import cn.caishen.report.common.exceptions.BusinessException;
import cn.caishen.report.common.utils.IntegerUtil;
import cn.caishen.report.common.utils.LbMap;
import cn.caishen.report.common.utils.StringUtil;
import cn.caishen.report.dao.system.ModuleDao;
import cn.caishen.report.domain.system.Module;
import cn.caishen.report.service.system.ModuleService;
import cn.caishen.report.vo.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 模块管理Service实现类
 *
 * @author LB
 */
@Service("moduleService")
@Transactional(rollbackFor = Throwable.class)
public class ModuleServiceImpl extends ServiceImpl<ModuleDao, Module> implements ModuleService {

    private final ModuleDao moduleDao;

    public ModuleServiceImpl(ModuleDao moduleDao) {
        this.moduleDao = moduleDao;
    }

    /**
     * 分页查询列表
     *
     * @param page
     * @param limit
     * @return
     */
    @Override
    public PageInfo<Module> getList(int page, int limit, LbMap param) {
        QueryWrapper<Module> wrapper = new QueryWrapper<>();
        wrapper.eq("delete_flag", LbConstant.DELETE_STATUS.UN_DELETE.getCode());

        if (StringUtil.isNotEmpty(param.getString("moduleName"))) {
            wrapper.like("module_name", param.getString("moduleName"));
        }

        PageHelper.startPage(page, limit);
        List<Module> list = moduleDao.selectList(wrapper);
        PageInfo<Module> pageInfo = new PageInfo<>(list);

        List<Module> newList = pageInfo.getList().stream().peek(x -> {
            Module parentModule = this.getById(x.getParentId());
            if (parentModule != null) x.setParentName(parentModule.getModuleName());
        }).collect(Collectors.toList());

        pageInfo.setList(newList);

        return pageInfo;
    }

    /**
     * 检查模块信息
     *
     * @param module
     * @return
     */
    private boolean checkInfoExists(Module module, Integer moduleId) {
        QueryWrapper<Module> wrapper = new QueryWrapper<Module>().eq("module_name", module.getModuleName());

        if (IntegerUtil.isEmpty(moduleId)) {
            wrapper.ne("module_id", moduleId);
        }
        List<Module> moduleList = this.list(wrapper);
        return moduleList.size() != 0;
    }

    /**
     * 新增信息
     *
     * @param module
     */
    @Override
    @SneakyThrows
    public void saveOne(Module module) {
        if (checkInfoExists(module, 0)) {
            throw new BusinessException("模块名称不能重复");
        }
        module.setDeleteFlag(LbConstant.DELETE_STATUS.UN_DELETE.getCode());
        int count = moduleDao.insert(module);
        if (count != 1) {
            throw new BusinessException("保存失败");
        }
    }

    /**
     * 更新信息
     *
     * @param module
     */
    @Override
    @SneakyThrows
    public void update(Module module) {
        if (checkInfoExists(module, module.getModuleId())) {
            throw new BusinessException("模块名称不能重复");
        }
        int count = moduleDao.updateById(module);
        if (count != 1) {
            throw new BusinessException("更新失败");
        }
    }

    /**
     * 删除信息
     *
     * @param primaryKey
     */
    @Override
    @SneakyThrows
    public void delete(String primaryKey) {
        Module module = moduleDao.selectById(primaryKey);

        Module newModule = new Module();
        newModule.setModuleId(Integer.valueOf(primaryKey));
        newModule.setDeleteFlag(LbConstant.DELETE_STATUS.DELETED.getCode());
        newModule.setModuleName(module.getModuleName() + "_" + IdWorker.get32UUID());
        int count = moduleDao.updateById(newModule);
        if (count != 1) {
            throw new BusinessException("删除失败");
        }
    }

    /**
     * 根据登录用户查询模块信息
     *
     * @param userVo
     * @return
     */
    @Override
    public List<Module> getModuleListByUser(UserVo userVo) {
        int userType = userVo.getUserType();
        QueryWrapper<Module> wrapper = new QueryWrapper<>();
        wrapper.eq("delete_flag", LbConstant.DELETE_STATUS.UN_DELETE.getCode()).orderByAsc("order_by");

        if (Objects.nonNull(userVo.getIsReport()) && userVo.getIsReport() == LbConstant.IS_REPORT.IS_REPORT.getCode()) {
            wrapper.eq("is_report", LbConstant.IS_REPORT.IS_REPORT.getCode());
        }

        if (userType == LbConstant.USER_TYPE.PLATFORM_ADMIN.getCode()) {
            //平台级管理员
            wrapper.eq("type", LbConstant.MODULE_TYPE.PLATFORM_MODULE.getCode());
            return this.list(wrapper);
        } else if (userType == LbConstant.USER_TYPE.UNIT_ADMIN.getCode()) {
            //商户管理员
            wrapper.eq("type", LbConstant.MODULE_TYPE.UNIT_MODULE.getCode());
            return this.list(wrapper);
        } else {
            return moduleDao.getModuleListByUserId(userVo.getUserId(), userVo.getUnitId(), userVo.getIsReport());
        }
    }

    /**
     * 查询所有商户模块
     *
     * @return
     */
    @Override
    @SneakyThrows
    public List<Module> getAllModule() {
        return this.list(new QueryWrapper<Module>()
                .eq("type", LbConstant.MODULE_TYPE.UNIT_MODULE.getCode())
                .eq("delete_flag", LbConstant.DELETE_STATUS.UN_DELETE.getCode()));
    }

    /**
     * 该角色本身有的商户模块
     *
     * @param roleId
     * @return
     */
    @Override
    @SneakyThrows
    public List<Module> getModuleListByRoleId(String roleId) {
        UserVo user = LoginInformation.getUser();
        return moduleDao.getModuleListByRoleId(Integer.valueOf(roleId), user.getUnitId());
    }

    /**
     * 查询所有报表模块
     *
     * @return
     */
    @Override
    @SneakyThrows
    public List<Module> getAllReportModule() {
        return this.list(new QueryWrapper<Module>()
                .eq("type", LbConstant.MODULE_TYPE.UNIT_MODULE.getCode())
                .eq("delete_flag", LbConstant.DELETE_STATUS.UN_DELETE.getCode())
                .eq("is_report", LbConstant.IS_REPORT.IS_REPORT.getCode()));
    }

    @Override
    public List<Module> getAllList(LbMap param) {
        return this.list();
    }
}
